package org.meb.speedway.bean;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.persistence.EntityManager;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.meb.speedway.config.SpeedwayDatabase;
import org.meb.speedway.model.event.Event;
import org.meb.speedway.model.event.EventRider;
import org.meb.speedway.model.event.EventRider.RiderKind;
import org.meb.speedway.model.registry.Rider;
import org.meb.speedway.model.registry.Team;
import org.meb.speedway.model.registry.TeamRiderHistory;
import org.meb.speedway.util.TeamResolver;

//@Singleton
//@Startup
public class DataInitServiceBean implements DataInitService {

	@Inject
	@SpeedwayDatabase
	private EntityManager em;

	@EJB
	private ImportService importService;

	public DataInitServiceBean() {
	}

	@PostConstruct
	public void initialize() throws Exception {
		InputStream stream = this.getClass().getResourceAsStream("/leagues.csv");
		List<String> lines = IOUtils.readLines(stream);
		String data = StringUtils.join(lines, "\n");
		String log = importService.importLeagues(data);
		System.out.println(log);

		stream = this.getClass().getResourceAsStream("/teams.csv");
		lines = IOUtils.readLines(stream);
		data = StringUtils.join(lines, "\n");
		log = importService.importTeams(data);
		System.out.println(log);
	}

	private void printData() {
		List<Event> meetings = em.createQuery("from Meeting", Event.class).getResultList();
		for (Event meeting : meetings) {
			System.out.println(meeting);
		}
	}

	private void initializeData() throws IOException {
		readAndPersistTeams();
		List<Team> teams = em.createQuery("from Team", Team.class).getResultList();
		readAndPersisRiders(teams);
		List<Rider> riders = em.createQuery("from Rider", Rider.class).getResultList();
		createAndPersisMeetings(teams, riders);
		createAndPersisMeetings(teams, riders);
		em.flush();
	}

	private void createAndPersisMeetings(List<Team> teams, List<Rider> riders) {
		int homeIdx = RandomUtils.nextInt(teams.size());
		Team homeTeam = teams.get(homeIdx);
		int awayIdx;
		while ((awayIdx = RandomUtils.nextInt(teams.size())) == homeIdx)
			;
		Team awayTeam = teams.get(awayIdx);
		System.out.println("home team: " + homeTeam);
		System.out.println("away team: " + awayTeam);

		Event meeting = new Event();
		meeting.setHomeTeam(homeTeam);
		meeting.setHomeEventRiders(createMeetingRiders(meeting, homeTeam, RiderKind.HOME));
		meeting.setAwayTeam(awayTeam);
		meeting.setAwayEventRiders(createMeetingRiders(meeting, awayTeam, RiderKind.AWAY));
		meeting.setDate(new Date());
		em.persist(meeting);
	}

	private List<EventRider> createMeetingRiders(Event event, Team team, RiderKind kind) {
		List<TeamRiderHistory> trhList = em
				.createQuery("from TeamRiderHistory where year = 2012 and team_id = :team_id",
						TeamRiderHistory.class).setParameter("team_id", team.getId())
				.getResultList();
		List<EventRider> eventRiders = new ArrayList<EventRider>();
		int ridersPerTeam = 3;
		int[] riderIdxs = new int[ridersPerTeam];
		int riderIdx;
		while (eventRiders.size() < ridersPerTeam) {
			riderIdx = RandomUtils.nextInt(trhList.size());
			if (!ArrayUtils.contains(riderIdxs, riderIdx)) {
				EventRider mr = new EventRider();
				mr.setRiderKind(kind);
				mr.setRider(trhList.get(riderIdx).getRider());
				mr.setEvent(event);
				eventRiders.add(mr);
			}
		}
		return eventRiders;
	}

	private void readAndPersisRiders(List<Team> teams) throws IOException {
		InputStream ridersIn = getClass().getResourceAsStream("/riders.csv");
		BufferedReader ridersReader = new BufferedReader(new InputStreamReader(ridersIn));
		String line = null;
		TeamResolver teamResolver = new TeamResolver(teams);
		while ((line = ridersReader.readLine()) != null) {
			if (StringUtils.isNotBlank(line)) {
				String[] tokens = line.trim().split(";");
				String riderName = tokens[0].trim();
				Rider rider = new Rider(riderName);
				rider.setTeamsHistory(new ArrayList<TeamRiderHistory>());

				for (int i = 1; i < tokens.length; i += 2) {
					Integer year = Integer.valueOf(tokens[i].trim());
					String teamName = tokens[i + 1].trim();

					Team team = teamResolver.resolve(teamName);
					if (team != null) {
						TeamRiderHistory trh = new TeamRiderHistory();
						trh.setYear(year);
						trh.setRider(rider);
						trh.setTeam(team);
						rider.getTeamsHistory().add(trh);
					} else {
						System.out.println("Unable to resolve: " + teamName);
					}
				}
				em.persist(rider);
			}
		}
	}

	private void readAndPersistTeams() throws IOException {
		InputStream teamsIn = getClass().getResourceAsStream("/teams.csv");
		BufferedReader teamsReader = new BufferedReader(new InputStreamReader(teamsIn));
		String line = null;
		while ((line = teamsReader.readLine()) != null) {
			if (StringUtils.isNotBlank(line)) {
				em.persist(new Team(line.trim()));
			}
		}
	}
}
